package com.impress;

import java.util.List;
import java.util.Set;

import com.impress.Utility.BadAccountException;
import com.impress.Utility.SDCardException;
import com.impress.model.Item;
import com.impress.service.ItemService;

import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.Service;
import android.content.Intent;
import android.content.SharedPreferences;
import android.os.Binder;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.util.Log;

public class SyncService extends Service {

	public static final String NOTIFY_CHANGE = SyncService.class.getName()+".NOTIFY_CHANGE";
	public static final String NOTIFY_LOGIN = SyncService.class.getName()+".NOTIFY_LOGIN"; 
	public static final String AUTO_SYNC = "auto_sync";
	public static final String UPLOAD_FINISH = "upload_only";
	
	private static final int FINISH_SERVICE = 0;
	private static final int STOP_SERVICE = 1;
	private static final int UPLOAD_SERVICE = 2;
	private static final int NEED_LOGIN = 3;
	private static final String TAG = "SyncService";
	
	private NotificationManager mNM;
	private final IBinder mBinder = new SyncBinder();
	private ItemService mItemService;
	private boolean isAutoService = false;
	private static byte[] lock = new byte[0];  //lock for synchronized
	
	public class SyncBinder extends Binder{
		SyncService getService(){
			return SyncService.this;
		}
	}
	
	@Override
	public IBinder onBind(Intent intent) {
		// TODO Auto-generated method stub
		return mBinder;
	}
	
	private final Handler handler = new Handler(){

		@Override
		public void handleMessage(Message msg) {
			switch (msg.what) {
			case FINISH_SERVICE:			//finish the service successfully.
				sendBroadcast(new Intent(NOTIFY_CHANGE));
				break;
			case STOP_SERVICE:		//stop the service because of exceptions
				SyncService.this.stopSelf();
				break;
			case UPLOAD_SERVICE:			//upload changes finished.
				mNM.cancel(R.string.updateNotifiString);
				Intent intent = new Intent(NOTIFY_CHANGE);
				intent.putExtra(UPLOAD_FINISH, true);
				sendBroadcast(intent);
				break;
			case NEED_LOGIN:			//invalid account info. login needed.
				sendBroadcast(new Intent(NOTIFY_LOGIN));
				break;
			default:
				break;
			}
			super.handleMessage(msg);
		}
		
	};

	@Override
	public void onCreate() {
		mItemService = new ItemService(this);
		mNM = (NotificationManager)getSystemService(NOTIFICATION_SERVICE);
	}
	
	//main function of synchronize to server.
	public void synchronization(final boolean isAuto){
		synchronized(lock){
			showNotification(R.string.updateNotifiString,MainListActivity.class);
			new Thread(){

				@Override
				public void run() {
					try {
						int capacity = 10;
						int autoMode = 2;
						Message message = new Message();
						SharedPreferences settings = getSharedPreferences(getPackageName()+"_preferences", MODE_PRIVATE);
						if (settings != null) {
							try {
								capacity = Integer.valueOf(settings.getString("reading_list_cap", "10"));
								autoMode = Integer.valueOf(settings.getString("auto_sync", "2"));
							} catch (Exception e) {
								Log.e(TAG, "preferences settings are not valid.");
							}
						}
						if (isAuto) {
							switch (autoMode) {
							//wifi-only mode
							case 2:
								if (mItemService.IsWifiConnected()) {
									break;
								}
								//enabled mode
							case 1:
								if (mItemService.IsNetworkConnected()) {
									break;
								}
								//disabled mode
							case 0:
							default:
								message.what = STOP_SERVICE;
								handler.sendMessage(message);
								return ;
							}
						}
						mItemService.SyncItemState();
						List<Item> oldItems = mItemService.getItemsFromDatabase(false);
						Set<Long> newItemIds = mItemService.GetItemsIds(capacity, 0);
						int length = newItemIds.size();
						mItemService.checkNewItemId(newItemIds, oldItems);
						if (newItemIds.isEmpty()) {

						}else if (newItemIds.size() == length) {
							//					if new ids are the same as the fetched item ids
							//					means there is no duplicate ids.
							mItemService.fetchNewItems(capacity, 0);
						}else {
							//						there are some duplicate ids in the id list.
							mItemService.fetchNewItems(newItemIds);
						}
						oldItems.clear();
						newItemIds.clear();
						if (isAuto) {
							if (settings != null) {
								SharedPreferences.Editor editor = settings.edit();
								editor.putString("last_update_time", 
										Utility.convertLongToDate(System.currentTimeMillis()));
								editor.commit();
							}
						}
						message.what = FINISH_SERVICE;
						handler.sendMessage(message);
						oldItems = mItemService.getItemsFromDatabase(true);
						mItemService.downloadItem(oldItems);

					} catch (Exception e) {
						Log.e(TAG, e.getMessage());
						if (e instanceof BadAccountException) {
							if (isAuto) {
								showNotification(R.string.badAccountInfoString, AccountLogin.class);
							}else {
								Message message = new Message();
								message.what = NEED_LOGIN;
								handler.sendMessage(message);
							}
						}else if (e instanceof SDCardException) {
						}

					}
					SyncService.this.stopSelf();
				}

			}.start();
		}
		
	}
	
	public void uploadChanges(){
		synchronized(lock){
			showNotification(R.string.updateNotifiString, MainListActivity.class);
			new Thread(){

				@Override
				public void run() {
					try {
						mItemService.SyncItemState();
						Message message = new Message();
						message.what = UPLOAD_SERVICE;
						handler.sendMessage(message);
					} catch (Exception e) {
						if (e instanceof BadAccountException) {
							showNotification(R.string.badAccountInfoString, AccountLogin.class);
						}
					}
				}

			}.start();
		}
	}

	@Override
	public int onStartCommand(Intent intent, int flags, int startId) {


		isAutoService = intent.getBooleanExtra(AUTO_SYNC, false);
		if (isAutoService) {
//			SharedPreferences settings = getSharedPreferences(
//					getPackageName()+"_preferences", MODE_PRIVATE);
//			SharedPreferences.Editor editor = settings.edit();
//			editor.putString("last_update_time", 
//					Utility.convertLongToDate(System.currentTimeMillis()));
//			editor.commit();
		}
		synchronized(lock){
		synchronization(isAutoService);		
		}
		return START_NOT_STICKY;
	}

	@Override
	public void onDestroy() {
		mNM.cancel(R.string.updateNotifiString);
		Log.d(TAG, "Service destroyed.");
	}
	
	private void showNotification(int resId, Class<?>cls){
		CharSequence text = getText(resId);
		Notification notification = new Notification(R.drawable.ico_notification, 
				text, System.currentTimeMillis());
		PendingIntent contentIntent = PendingIntent.getActivity(this, 0, 
				new Intent(this, cls), 0);
		notification.setLatestEventInfo(this, getText(R.string.app_name), text, contentIntent);
		mNM.notify(R.string.updateNotifiString, notification);
		
	}

}
